﻿
namespace Aeon.Emulator.Instructions.Stack
{
    internal static class Push
    {
        [Opcode("6A ibx", AddressSize = 16 | 32)]
        public static void PushByte(VirtualMachine vm, short value)
        {
            vm.PushToStack((ushort)value);
        }
        [Alternate("PushByte", AddressSize = 16 | 32)]
        public static void PushByteToDWord(VirtualMachine vm, int value)
        {
            vm.PushToStack32((uint)value);
        }

        [Opcode("FF/6 rmw|50+ rw|68 iw", AddressSize = 16 | 32)]
        public static void PushWord(VirtualMachine vm, ushort value)
        {
            vm.PushToStack(value);
        }
        [Alternate("PushWord", AddressSize = 16 | 32)]
        public static void PushDWord(VirtualMachine vm, uint value)
        {
            vm.PushToStack32(value);
        }

        [Opcode("9C", Name = "pushf", AddressSize = 16 | 32)]
        public static void PushFlags(VirtualMachine vm)
        {
            vm.PushToStack((ushort)vm.Processor.Flags);

            vm.Processor.InstructionEpilog();
        }
        [Alternate("PushFlags", AddressSize = 16 | 32)]
        public static void PushFlags32(VirtualMachine vm)
        {
            vm.PushToStack32((uint)vm.Processor.Flags);

            vm.Processor.InstructionEpilog();
        }

        [Opcode("60", Name = "pusha", AddressSize = 16 | 32)]
        public static void PushAll(VirtualMachine vm)
        {
            ushort sp = vm.Processor.SP;
            vm.PushToStack((ushort)vm.Processor.AX);
            vm.PushToStack((ushort)vm.Processor.CX);
            vm.PushToStack((ushort)vm.Processor.DX);
            vm.PushToStack((ushort)vm.Processor.BX);
            vm.PushToStack(sp);
            vm.PushToStack(vm.Processor.BP);
            vm.PushToStack(vm.Processor.SI);
            vm.PushToStack(vm.Processor.DI);

            vm.Processor.InstructionEpilog();
        }
        [Alternate("PushAll", AddressSize = 16 | 32)]
        public static void PushAll32(VirtualMachine vm)
        {
            uint esp = vm.Processor.ESP;
            vm.PushToStack32((uint)vm.Processor.EAX);
            vm.PushToStack32((uint)vm.Processor.ECX);
            vm.PushToStack32((uint)vm.Processor.EDX);
            vm.PushToStack32((uint)vm.Processor.EBX);
            vm.PushToStack32(esp);
            vm.PushToStack32(vm.Processor.EBP);
            vm.PushToStack32(vm.Processor.ESI);
            vm.PushToStack32(vm.Processor.EDI);

            vm.Processor.InstructionEpilog();
        }

        [Opcode("61", Name = "popa", AddressSize = 16 | 32)]
        public static void PopAll(VirtualMachine vm)
        {
            vm.Processor.DI = vm.PopFromStack();
            vm.Processor.SI = vm.PopFromStack();
            vm.Processor.BP = vm.PopFromStack();
            vm.AddToStackPointer(2);
            vm.Processor.BX = (short)vm.PopFromStack();
            vm.Processor.DX = (short)vm.PopFromStack();
            vm.Processor.CX = (short)vm.PopFromStack();
            vm.Processor.AX = (short)vm.PopFromStack();

            vm.Processor.InstructionEpilog();
        }
        [Alternate("PopAll", AddressSize = 16 | 32)]
        public static void PopAll32(VirtualMachine vm)
        {
            vm.Processor.EDI = vm.PopFromStack32();
            vm.Processor.ESI = vm.PopFromStack32();
            vm.Processor.EBP = vm.PopFromStack32();
            vm.AddToStackPointer(4);
            vm.Processor.EBX = (int)vm.PopFromStack32();
            vm.Processor.EDX = (int)vm.PopFromStack32();
            vm.Processor.ECX = (int)vm.PopFromStack32();
            vm.Processor.EAX = (int)vm.PopFromStack32();

            vm.Processor.InstructionEpilog();
        }
    }
}
